package pri.hillchen.std.simpledemo.javaapi;
import org.apache.zookeeper.*;

/**
 * @author:hillchen
 * @DESCRIPTION:
 * @Date: Created in 12:37 2018/3/12 0012.
 */
public class JavaApiDistributeLocak implements DistributeLock {
    public static final String BASE_PATH = "/locks";
    private ZooKeeper zooKeeper;

    public JavaApiDistributeLocak(ZooKeeper zooKeeper) {
        this.zooKeeper = zooKeeper;
    }

    @Override
    public boolean lock(String lockName,LockedSuccHandel succHandel, LockedFailHandel failHandel, LockedExceptionHandel lockedExceptionHandel){
        String lockPath =createLockPath(lockName);
        zooKeeper.create(lockPath,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,(rc,path,ctx,name) ->{

            try {
                switch (KeeperException.Code.get(rc)) {
                    case OK:
                        System.out.println("获得锁成功！");
                        succHandel.handelSucc();
                        this.unlock(lockName);
                        break;
                    default: {
                        System.out.println("获得锁成功！");
                        failHandel.handelFail();
                        zooKeeper.exists(lockPath, (WatchedEvent watchEvent) -> {
                            if(Watcher.Event.EventType.NodeDeleted == watchEvent.getType()){
                                lock(lockName,succHandel,failHandel,lockedExceptionHandel);
                            }
                        });
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                lockedExceptionHandel.handelException(e);
            }
        },null);
        return false;
    }

    private String createLockPath(String lockName){
        return BASE_PATH + "/"+lockName;
    }
    @Override
    public boolean unlock(String lockName) {
        try {
            zooKeeper.delete(createLockPath(lockName),-1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
        return true;
    }
}
